package com.ehualu.msg.service.impl;

import java.lang.reflect.Method;
import java.util.Map;
import javax.inject.Inject;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.ehualu.core.util.sms.pojo.Sms;
import com.ehualu.core.util.sms.pojo.SmsResponse;
import com.ehualu.msg.Model.MsgModel;
import com.ehualu.msg.dao.ApplicationMapperDao;
import com.ehualu.msg.pojo.ApplicationMapper;
import com.ehualu.msg.service.MessageService;
import com.ehualu.msg.util.TimesLimitMapUtil;
import com.google.common.util.concurrent.RateLimiter;

@Service
public class MessageServiceImpl implements MessageService {

	private static final Logger logger = LoggerFactory.getLogger(MessageServiceImpl.class);

	@Inject
	private ApplicationMapperDao applicationMapperDao;
	
	@Override
	public SmsResponse sendMsg(MsgModel msg) {
		String applicationId = msg.getApplicationId();
		String phone = msg.getPhone();
		String message = msg.getMessage();
		String type = msg.getType();
		logger.debug("--------------------come into sendMsg---------------");
		logger.debug("---------applicationId--------" + applicationId);
		logger.debug("---------message--------" + message);
		logger.debug("---------phone--------" + phone);
		logger.debug("---------type--------" + type);

		if(StringUtils.isBlank(message) || StringUtils.isBlank(phone) || StringUtils.isBlank(applicationId)){
			return new SmsResponse("failed","201","parameter is blank");
		}
		// 初始化applicationMap,针对application设置发短信限制
		Map<String, RateLimiter> limitMap = TimesLimitMapUtil.getInstance();
		RateLimiter limiter = null;
		// 判断某个application的某种类型短信服务的发送短信是否超限
		StringBuilder appLimit = new StringBuilder();
		appLimit.append(applicationId).append("-").append(type);
		if (!limitMap.containsKey(appLimit.toString())) {
			limiter = RateLimiter.create(1);
			limitMap.put(appLimit.toString(), limiter);
		} else {
			limiter = limitMap.get(appLimit.toString());
		}

		if (!limiter.tryAcquire()) {
			return new SmsResponse("failed","202","application times reach limit");
		}
		//// 判断某个application下的某种类型短信服务的手机号的发送短信服务是否超限
		StringBuilder phoneLimit = new StringBuilder();
		phoneLimit.append(applicationId).append("-").append(type).append("-").append(phone);
		if (!limitMap.containsKey(phoneLimit.toString())) {
			limiter = RateLimiter.create(0.03);
			limitMap.put(phoneLimit.toString(), limiter);
		} else {
			limiter = limitMap.get(phoneLimit.toString());
		}
		if (!limiter.tryAcquire()) {
			return new SmsResponse("failed","202","phone times reach limit");
		}
		try {
			ApplicationMapper applicationMapper = applicationMapperDao.queryJobClass(applicationId);
			String clazz = applicationMapper.getMsgClassName();
			Sms sms = new Sms();
			sms.setPhone(phone);
			sms.setMessage(message);
			new smsSender(clazz,sms).start();
			SmsResponse smsr = new SmsResponse("success","0000","");
			return smsr;
		} catch (Exception e) {
			e.printStackTrace();
			return new SmsResponse("failed","002","system exception");
		}
	}
	
	private class smsSender extends Thread{
		private String classname;
		private Sms message;
		private int retry = 3;
		
		public smsSender(String classname, Sms message){
			this.classname = classname;
			this.message = message;
		}
		
		private String sendmsg(){
			try {
				Class clazz = Class.forName(classname);
				Method method = clazz.getMethod("sendSms", Sms.class);
				String result = (String) method.invoke(clazz.newInstance(), message);
				return result;
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
		}
		@Override
		public void run() {
			while(retry > 0){
				String result = sendmsg();
				System.out.println("result="+result);
				SmsResponse smsr = JSON.parseObject(result, SmsResponse.class);
				if(smsr.getErrorcode().equals("0006") || smsr.getErrorcode().equals("0002")){
					retry-=1;
					continue;
				}
				if (! smsr.getErrorcode().equals("0000")){
					logger.error("message send error with error request info");
					logger.error(classname);
					logger.error(message.toString());
				}
				break;
			}
		}
	}
}
